/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ueb15;

/**
 *
 * @author adier
 */
public class NodeImpl implements Node, Comparable {

    private Object           iData           = null;              
    private double           dData;    
    private boolean          isBlack         = true;
    private NodeImpl         leftChild       = null;        
    private NodeImpl         rightChild      = null;       
    private NodeImpl         parent          = null;


    protected NodeImpl(NodeImpl parent) {
        this.parent=parent;
    }


    /**
     * returns the leftchild of the node
     * 
     * @return the leftchild
     */
    @Override
    public NodeImpl getLeftChild() {
        if(this == null)
        {
            return null;
        }
        return this.leftChild;
    }
    
    /**
     * returns the parent of the node
     * 
     * @return the parent
     */
    @Override
    public NodeImpl getParent() {
        return this.parent;
    }
    
    /**
     * returns true if the node is black
     * 
     * @return true if node is <b>black</b>
     */
    @Override
    public boolean isBlack() {
        return this.isBlack;
    }
    
    /**
     * returns true if the node is <b>red</b>
     * 
     * @return true if node is <b>red</b>
     */
    public boolean isRed() {
        return !isBlack();
    }

    /**
     * makes node <b>black</b>
     */
    protected void makeBlack() {
        this.isBlack    =   true;
    }

    /**
     * makes node <b>red</b>
     */
    protected void makeRed() {
        this.isBlack    =   false;
    }

    /**
     * returns the rightchild
     * 
     * @return rightchild
     */
    @Override
    public NodeImpl getRightChild() {
        if(this!=null)
        {
            return this.rightChild;
        }
        else
        {
            return null;
        }
    }

    /**
     * returns the iData
     * 
     * @return iData
     */
    @Override
    public Object getiData() {
        return iData;
    }

    /**
     * returns true if iData is <b><i>null</i></b>
     * 
     * @return true if iData is <b><i>null</i></b>
     */
    @Override
    public boolean isNil() {
        if(this.iData==null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * returns the rightchild
     * 
     * @return rightchild
     */
    @Override
    public boolean isRightChild() {
        return this.equals(this.getParent().getRightChild());
        /*if(getParent()==null)
                return false;
        else
                return (this==getParent().getRightChild());	*/
    }

    /**
     * is the node a leftchild
     * 
     * @return true if node is leftchild
     */
    public boolean isLeftChild() {
        return !isRightChild();
    }
	
    /**
     * get the brother of the node
     * 
     * @return brother
     */
    public NodeImpl getBrother() {
        if(getParent()==null)
            return null;
        else
        {
            if(this.isRightChild())
            {
                return (this.getParent().getLeftChild());
            }
            else
            {
                return (this.getParent().getRightChild());
            }
        }
    }

    /**
     * get the uncle of the node
     * 
     * @return uncle
     */
    @Override
    public NodeImpl getUncle() {
        if((this.getParent()==null)||(this.getGrandparent()==null))
            return null;
        if(this.getParent().isRightChild())
        {
            if(((this.getParent().getParent().getLeftChild()!=null))||(!(this.getParent().getParent().getLeftChild().isNil())))
            {
                return this.getParent().getParent().getLeftChild();
            }
            else
            {
                return null;
            }
        }
        else
        {
            if(((this.getParent().getParent().getRightChild()!=null))||(!(this.getParent().getParent().getRightChild().isNil())))
            {
                return this.getParent().getParent().getRightChild();
            }
            else
            {
                return null;
            }
        }
    }
	
    /**
     * get grandparent
     * 
     * @return grandparent
     */
    @Override
    public NodeImpl getGrandparent() {
        if(this.getParent()==null)
            return null;
        if(this.getParent().getParent()!=null)
        {
            return this.getParent().getParent();
        }
        else
        {
            return null;
        }
    }

    /**
     * the maximum of the childs
     * 
     * @return maximum node
     */
    @Override
    public NodeImpl getMax() {
        if(!(getRightChild().isNil()))
        {
            return getRightChild().getMax();
        }
        else
        {
            return this;
        }
    }
    
    /**
     * the minimum of the childs
     * 
     * @return minimum node
     */
    @Override
    public NodeImpl getMin() {
        if(!(getLeftChild().isNil()))
        {
            return getLeftChild().getMin();
        }
        else
        {
            return this;
        }
    }
	
    /*public Integer getTreeMax() {
            getRoot().getMax();
            return getTreeMax;
    }

    public NodeImpl getRoot() {
            if(this.isRoot())
            {
                    this.getParent().getRoot();
            }
            return this;
    }*/
	
    /**
     * is the current node root
     * 
     * @return true if node is root
     */
    @Override
    public boolean isRoot() {
        if(this.parent==null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * sets the leftchild
     * 
     * @param leftChild     the new leftchild
     */
    protected void setLeftChild(NodeImpl leftChild) {
        if(leftChild==null)
        {
            this.leftChild = null;
        }
        else
        {
            this.leftChild = leftChild;
        }
        if ( leftChild != null )
            this.leftChild.setParent(this);
    }
	
    /**
     * has the node a leftchild
     * 
     * @return true if node has a leftchild
     */
    protected boolean hasLeftChild() {
        if(this.leftChild.getiData()!=null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * has the node a rightchild
     * 
     * @return true if node has a rightchild
     */
    protected boolean hasRightChild() {
        if(this.leftChild.getiData()!=null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * the parent of the node
     * 
     * @param parent    new parent
     */
    protected void setParent(NodeImpl parent) {
        if(parent==null)
        {
            this.parent=null;
        }
        else
        {
            this.parent=parent;
        }
    }

    /**
     * sets the rightchild
     * 
     * @param rightChild    new rightchild
     */
    protected void setRightChild(NodeImpl rightChild) {
        if(rightChild==null)
        {
            this.rightChild = null;
        }
        else
        {
            this.rightChild = rightChild;
        }
        if ( rightChild != null )
            this.rightChild.setParent(this);
    }

    /**
     * get dData
     * 
     * @return dData
     */
    @Override
    public double getdData() {
        return dData;
    }

    /**
     * set dData
     * 
     * @param dData     new dData
     */
    @Override
    public void setdData(double dData) {
        this.dData = dData;
    }

    /**
     * sets iData
     * 
     * @param iData 
     */
    @Override
    public void setiData(Object iData) {
        this.iData = iData;
    }

    @Override
    public int compareTo(Object o) {
        return ((Comparable) iData).compareTo((Comparable) o);
    }

    @Override
    public String toString() {
        StringBuffer string = new StringBuffer("[");

        string.append(getiData());

        string.append("]");
        return string.toString();
        
    }

}
